#pragma once
#include "EngineHead.h"
#include "Vector.h"
#include "Shader.h"
namespace mini
{
	class CMeshUnit;
	class CShaderUnit;
	class CBoundBox
	{
		friend class CModel;
		friend class CMeshUnit;

	public:
		CBoundBox(CPoint3F min, CPoint3F max);
		CBoundBox();
		~CBoundBox();
		void setPosition(const CPoint3F& pt);
		void setScale(const CPoint3F& scale);
		void setRotation(const CPoint3F& rotation);
		void setRadius(const CPoint3F& radius);
		void relateMeshUnit(CMeshUnit* pMeshUnit);
		template<typename T>
		void calculation(T* pData, size_t size);
		CPoint3F& getCenterPt();
		CPoint3F& getRadius();
		const CPoint3F& getMinPos()const;
		const CPoint3F& getMaxPos()const;
		const CPoint3F& size()const;
		const CPoint3F& getOriginalMinPos()const;
		const CPoint3F& getOriginalMaxPos()const;

		void setVisible(bool bValue);
		void show();
		void hide();
		bool isShow();
		bool checkPoint(const CPoint3F& p);
		bool checkBoundBox(const CBoundBox& boundbox);
		bool checkBoundBox(const CBoundBox& boundbox, CBoundBox* pBoundBox);
		bool inSideBoundBox(const CBoundBox& bigAABB);
		void reset();
		void draw(DeviceContext* pDeviceContext);
		void setBoundBoxRange(const CPoint3F& fMin, const CPoint3F& fMax);
		void setBoundBoxRange(float fValue);
		void update(CMatrix& worldMatrix);
		void editorPosition(const CPoint3F& p);
		bool operator == (const CBoundBox& box);

	public:
		static CShaderUnit*	gShaderUnitLine;
		static bool		gbCreateShader;

	private:
		bool initialiseBuffer();
		void fillLineData();

	public:
		CPoint3F mMinPos;
		CPoint3F mMaxPos;
		CPoint3F mPt;
		CPoint3F mRadius;
		CPoint3F mBoundBoxPit[8];
		CPoint3F mSize;
		CPoint3F mOriginalMinPos;
		CPoint3F mOriginalMaxPos;
		CPoint3F mOriginalPt;
		CPoint3F mOriginalRadius;
		CVector  mOriginalBoundBoxPit[8];

		float	mRadiusLength = 0;
		bool mbDirty =false;
		bool mVisible = false;
		CMeshUnit* mpMeshUnit = nullptr;
		ID3D11Buffer *m_linesBuffer = nullptr;
		INT32		mDrawLinePointCount;
		std::vector<VertexFormatVC>	m_lines;
		static CMatrix	gWorldMatrix;
		static float gOffset;
	};

	template<typename T>
	void CBoundBox::calculation(T* pData, size_t size)
	{
#define compare( index, value ) \
		if (pData[index].position.value < min.value)\
		{\
			min.value = pData[index].position.value; \
		}\
		if (pData[index].position.value > max.value)\
		{\
			max.value = pData[index].position.value; \
		}
		mOriginalMinPos = { FLT_MAX, FLT_MAX, FLT_MAX };
		mOriginalMaxPos = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
		CPoint3F& min = mOriginalMinPos;
		CPoint3F& max = mOriginalMaxPos;
		
		for (size_t i = 0; i < size; ++i)
		{
			compare(i, x);
			compare(i, y);
			compare(i, z);
		}
		setBoundBoxRange(mOriginalMinPos, mOriginalMaxPos);

	}
}
